package com.util.sm3;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

/**
 * 对硬件的data段(含有[ ])进行sm3密钥校验
 * 
 * @author Pingfan
 *
 */
public class Sm3Util {
	
	private static final String ENCODING = "UTF-8";

	/**
	 * SM3加密(带RU2000密钥)
	 * @param paramStr	待加密字符串
	 * @return	返回加密后，固定长度=32的16进制字符串
	 */
	public static String encrypt(String paramStr,String keyStr) {
		//将返回的hash值转换为16进制字符串
		String resultHexString = "";
		try {
			//将字符串转换成byte数组
			byte[] srcData = paramStr.getBytes(ENCODING);
			byte[] sm3Key = keyStr.getBytes(ENCODING);
			byte[] resultHash = hash(srcData,sm3Key);
			//将返回的hash值转换成16进制字符串
			resultHexString = ByteUtils.toHexString(resultHash);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return resultHexString;
	}
	
	/**
	 * 返回长度为32的byte数组
	 * 生成对应的hash值
	 * @param srcData
	 * @return
	 */
	public static byte[] hash(byte[] srcData, byte[] sm3Key){
		SM3Digest digest = new SM3Digest();
		digest.update(sm3Key, 0, sm3Key.length);
		digest.update(srcData, 0, srcData.length);
		byte[] hash = new byte[digest.getDigestSize()];
		digest.doFinal(hash, 0);
		return hash;
	}
	
	/**
	 * 通过hmac密钥进行加密(目前不适用RU2000)
	 * @param key 密钥
	 * @param srcData 被加密的byte数组
	 * @return
	 */
	public static byte[] hmac(byte[] key,byte[] srcData){
		KeyParameter keyParameter = new KeyParameter(key);
		SM3Digest digest = new SM3Digest();
		HMac mac = new HMac(digest);
		mac.init(keyParameter);
		mac.update(srcData,0,srcData.length);
		byte[] result = new byte[mac.getMacSize()];
		mac.doFinal(result, 0);
		return result;
	}
	/**
	 * 判断数据源与加密数据是否一致，通过验证原数组和生成是hash数组是否为同一数组，验证二者是否为同一数据
	 * @param srcStr
	 * @param sm3HexString
	 * @return
	 */
	public static boolean vertify(String srcStr, String keyStr, String sm3HexString){
		boolean flag = false;
		try {
			byte[] srcData = srcStr.getBytes(ENCODING);
			byte[] sm3Key = keyStr.getBytes(ENCODING);
			byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
			byte[] newHash = hash(srcData, sm3Key);
			if(Arrays.equals(newHash, sm3Hash));
				flag = true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return flag;
	}
	
//	public static void main(String[] args){
//		// 带密钥测试
//		String data = "[{\"u\":5,\"og\":\"00000000\",\"ng\":\"bc4bf17f\"},{\"u\":7,\"og\":\"00000000\",\"ng\":\"bf3ebdb4\"},{\"u\":8,\"og\":\"00000000\",\"ng\":\"bc2400da\"}]";
//		String key = "HGKGDYH1qaz@WSSX";
//	    String hex = Sm3Util.encrypt(data, key);
//		System.out.println(hex);
//		
//		//验证加密后的16进制字符串与加密前的字符串是否相同
//		boolean flag = Sm3Util.vertify(data, key, hex);
//		System.out.println(flag);
//	}
}
